Purpose

  • Explore sexual size dimorphism in hummingbird species from Costa Rica

  • Evaluate Rensch’s Rule

 

Report overview

 

Explore data

# read data
dat <- as.data.frame(read_excel("./data/raw/supplementary data.xlsx"))

# read tree
tree <- read.tree("./data/raw/imputed hummer tree 339 spp.tre")

dat$`scientific name`[dat$`scientific name` == "Phaetornis guy"] <- "Phaethornis guy"
dat$`scientific name`[dat$`scientific name` == "Phaetornis longirostris"] <- "Phaethornis longirostris"
dat$`scientific name`[dat$`scientific name` == "Heliomaster longisrostris"] <- "Heliomaster longirostris"
dat$scientific_name <- gsub(" ", "_", dat$`scientific name`)

tree$tip.label[tree$tip.label == "Amazilia_amabilis"] <- "Polyerata_amabilis"
tree$tip.label[tree$tip.label == "Hylocharis_eliciae"] <- "Chlorestes_eliciae"
tree$tip.label[tree$tip.label == "Chlorostilbon_canivetii"] <- "Cynanthus_canivetii"
tree$tip.label[tree$tip.label == "Elvira_cupreiceps"] <- "Microchera_cupreiceps"
tree$tip.label[tree$tip.label == "Calliphlox_bryantae"] <- "Philodice_bryantae"
tree$tip.label[tree$tip.label == "Amazilia_edward"] <- "Saucerottia_edward"
tree$tip.label[tree$tip.label == "Amazilia_saucerottei"] <- "Saucerottia_hoffmanni"
tree$tip.label[tree$tip.label == "Amazilia_saucerottei"] <- "Saucerottia_hoffmanni"
tree$tip.label[tree$tip.label == "Amazilia_candida"] <- "Chlorestes_candida"
tree$tip.label[tree$tip.label == "Elvira_chionura"] <- "Microchera_chonura"

# setdiff(unique(dat$scientific_name), tree$tip.label)

subtree <- drop.tip(phy = tree, tip = setdiff(tree$tip.label, unique(dat$scientific_name)))

names(dat) <- gsub(" ", ".", names(dat))

subtree2 <- subtree
subtree2$tip.label <- gsub("_", " ", subtree2$tip.label)
ggtree(subtree2, layout = "circular", col = viridis(10)[7]) + geom_tiplab(size = 4) +
    theme(plot.margin = unit(c(30, 10, 30, 10), "mm"))

# add log 10 variables
dat$lg10.female.weight <- log10(dat$female.weight)
dat$lg10.male.weight <- log10(dat$male.weight)

Run statistical models

Size comparison among sexes

log(females) ~ log(males)

(note that in the data supplied ln.SEX.weight variables are in natural log)

# model settings
v.cv.tree <- ape::vcv.phylo(subtree)

prior <- c(prior(normal(0, 10), "b"), prior(normal(0, 50), "Intercept"),
    prior(student_t(3, 0, 20), "sd"), prior(student_t(3, 0, 20), "sigma"))

iter <- 10000
male_x_mod <- brm(ln.female.weight ~ ln.male.weight + (1 | gr(scientific_name,
    cov = v.cv.tree)), data = dat, family = gaussian(), data2 = list(v.cv.tree = v.cv.tree),
    prior = prior, iter = iter, control = list(adapt_delta = 0.99,
        max_treedepth = 15), file = "./data/processed/male_vs_female_size",
    file_refit = "always")
html_summary(read.file = "./data/processed/male_vs_female_size.rds",
    highlight = TRUE)

male_vs_female_size

priors formula iterations chains thinning warmup diverg_transitions rhats > 1.05 min_bulk_ESS min_tail_ESS seed
1 b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) ln.female.weight ~ ln.male.weight + (1 | gr(scientific_name, cov = v.cv.tree)) 10000 4 1 5000 0 0 9817.964 11867.65 130978144
Estimate l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
b_Intercept 0.197 0.085 0.313 1.001 9817.964 11867.65
b_ln.male.weight 0.838 0.780 0.897 1 14809.620 13099.05

log10(females) ~ log10(males)

log10_male_x_mod <- brm(lg10.female.weight ~ lg10.male.weight + (1 |
    gr(scientific_name, cov = v.cv.tree)), data = dat, family = gaussian(),
    data2 = list(v.cv.tree = v.cv.tree), prior = prior, iter = iter,
    control = list(adapt_delta = 0.99, max_treedepth = 15), file = "./data/processed/log10_male_vs_female_size",
    file_refit = "always")
html_summary(read.file = "./data/processed/log10_male_vs_female_size.rds",
    highlight = TRUE)

log10_male_vs_female_size

priors formula iterations chains thinning warmup diverg_transitions rhats > 1.05 min_bulk_ESS min_tail_ESS seed
1 b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) lg10.female.weight ~ lg10.male.weight + (1 | gr(scientific_name, cov = v.cv.tree)) 10000 4 1 5000 0 0 12310.95 12983.13 408928919
Estimate l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
b_Intercept 0.086 0.038 0.137 1 12310.95 12983.13
b_lg10.male.weight 0.838 0.779 0.896 1 16789.93 14729.30

log(males) ~ log(females)

female_x_mod <- brm(ln.male.weight ~ ln.female.weight + (1 | gr(scientific_name,
    cov = v.cv.tree)), data = dat, family = gaussian(), data2 = list(v.cv.tree = v.cv.tree),
    prior = prior, iter = iter, control = list(adapt_delta = 0.99,
        max_treedepth = 15), file = "./data/processed/female_vs_male_size",
    file_refit = "always")
html_summary(read.file = "./data/processed/female_vs_male_size.rds",
    highlight = TRUE)

female_vs_male_size

priors formula iterations chains thinning warmup diverg_transitions rhats > 1.05 min_bulk_ESS min_tail_ESS seed
1 b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) ln.male.weight ~ ln.female.weight + (1 | gr(scientific_name, cov = v.cv.tree)) 10000 4 1 5000 0 0 12599.43 12003.39 1212623959
Estimate l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
b_Intercept -0.147 -0.288 -0.006 1 12599.43 12003.39
b_ln.female.weight 1.139 1.061 1.215 1 15499.92 14691.24

log10(males) ~ log10(females)

log10_female_x_mod <- brm(lg10.male.weight ~ lg10.female.weight +
    (1 | gr(scientific_name, cov = v.cv.tree)), data = dat, family = gaussian(),
    data2 = list(v.cv.tree = v.cv.tree), prior = prior, iter = iter,
    control = list(adapt_delta = 0.99, max_treedepth = 15), file = "./data/processed/log10_female_vs_male_size",
    file_refit = "always")
html_summary(read.file = "./data/processed/log10_female_vs_male_size.rds",
    highlight = TRUE)

log10_female_vs_male_size

priors formula iterations chains thinning warmup diverg_transitions rhats > 1.05 min_bulk_ESS min_tail_ESS seed
1 b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) lg10.male.weight ~ lg10.female.weight + (1 | gr(scientific_name, cov = v.cv.tree)) 10000 4 1 5000 0 0 16768.06 15102.63 769877839
Estimate l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
b_Intercept -0.064 -0.127 -0.002 1 16768.06 15511.65
b_lg10.female.weight 1.139 1.061 1.217 1 20912.58 15102.63

SSD (Lovich-Gibbons ratio) vs male size

  • SSD represented as aboslute Lovich-Gibbons ratio
  • sex size as log of weight

Absolute SSD vs log male size

male_vs_ssd_mod <- brm(aboluteSSD ~ ln.male.weight + (1 | gr(scientific_name,
    cov = v.cv.tree)), data = dat, family = gaussian(), data2 = list(v.cv.tree = v.cv.tree),
    prior = prior, iter = iter, control = list(adapt_delta = 0.99,
        max_treedepth = 15), file = "./data/processed/male_vs_abs_SSD",
    file_refit = "always")
html_summary(read.file = "./data/processed/male_vs_abs_SSD.rds", highlight = TRUE)

male_vs_abs_SSD

priors formula iterations chains thinning warmup diverg_transitions rhats > 1.05 min_bulk_ESS min_tail_ESS seed
1 b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) aboluteSSD ~ ln.male.weight + (1 | gr(scientific_name, cov = v.cv.tree)) 10000 4 1 5000 0 0 18468.74 14046.47 920571681
Estimate l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
b_Intercept 0.011 -0.099 0.116 1 18468.74 14046.47
b_ln.male.weight 0.065 0.006 0.123 1.001 25029.29 15934.31

Absolute SSD vs log10 male size

log10_male_vs_ssd_mod <- brm(aboluteSSD ~ lg10.male.weight + (1 |
    gr(scientific_name, cov = v.cv.tree)), data = dat, family = gaussian(),
    data2 = list(v.cv.tree = v.cv.tree), prior = prior, iter = iter,
    control = list(adapt_delta = 0.99, max_treedepth = 15), file = "./data/processed/log10_male_vs_abs_SSD",
    file_refit = "always")
html_summary(read.file = "./data/processed/log10_male_vs_abs_SSD.rds",
    highlight = TRUE)

log10_male_vs_abs_SSD

priors formula iterations chains thinning warmup diverg_transitions rhats > 1.05 min_bulk_ESS min_tail_ESS seed
1 b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) aboluteSSD ~ lg10.male.weight + (1 | gr(scientific_name, cov = v.cv.tree)) 10000 4 1 5000 0 0 14877.92 11685.19 416614627
Estimate l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
b_Intercept 0.011 -0.101 0.113 1.001 14877.92 11685.19
b_lg10.male.weight 0.150 0.019 0.286 1.001 20376.34 14563.92

absolute SSD vs log female size

female_vs_ssd_mod <- brm(aboluteSSD ~ ln.female.weight + (1 | gr(scientific_name,
    cov = v.cv.tree)), data = dat, family = gaussian(), data2 = list(v.cv.tree = v.cv.tree),
    prior = prior, iter = iter, control = list(adapt_delta = 0.99,
        max_treedepth = 15), file = "./data/processed/female_vs_abs_SSD.rds",
    file_refit = "always")
html_summary(read.file = "./data/processed/female_vs_abs_SSD.rds",
    highlight = TRUE)

female_vs_abs_SSD

priors formula iterations chains thinning warmup diverg_transitions rhats > 1.05 min_bulk_ESS min_tail_ESS seed
1 b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) aboluteSSD ~ ln.female.weight + (1 | gr(scientific_name, cov = v.cv.tree)) 10000 4 1 5000 0 0 19482.34 14833.66 65846261
Estimate l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
b_Intercept 0.053 -0.065 0.167 1 19482.34 14833.66
b_ln.female.weight 0.042 -0.027 0.111 1 25007.44 15677.30

absolute SSD vs log10 female size

log10_female_vs_ssd_mod <- brm(aboluteSSD ~ lg10.female.weight + (1 |
    gr(scientific_name, cov = v.cv.tree)), data = dat, family = gaussian(),
    data2 = list(v.cv.tree = v.cv.tree), prior = prior, iter = iter,
    control = list(adapt_delta = 0.99, max_treedepth = 15), file = "./data/processed/log10_female_vs_abs_SSD",
    file_refit = "always")
html_summary(read.file = "./data/processed/log10_female_vs_abs_SSD.rds",
    highlight = TRUE)

log10_female_vs_abs_SSD

priors formula iterations chains thinning warmup diverg_transitions rhats > 1.05 min_bulk_ESS min_tail_ESS seed
1 b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) aboluteSSD ~ lg10.female.weight + (1 | gr(scientific_name, cov = v.cv.tree)) 10000 4 1 5000 0 0 15257.46 13088.31 1833450209
Estimate l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
b_Intercept 0.052 -0.070 0.168 1 15257.46 13088.31
b_lg10.female.weight 0.098 -0.062 0.258 1 20374.40 15549.23

Graphs

Male vs female body mass

fit <- readRDS("./data/processed/log10_male_vs_female_size.rds")

gg_fit <- conditional_effects(fit)

pred_dat <- gg_fit$lg10.male.weight

fit_summ <- draw_summary(posterior::as_draws_array(fit), variables = c("b_Intercept",
    "b_lg10.male.weight"), robust = TRUE, probs = c(0.025, 0.975))

ggplot(data = dat, mapping = aes(x = lg10.male.weight, y = lg10.female.weight)) +
    geom_segment(data = pred_dat, mapping = aes(x = min(pred_dat$lg10.male.weight),
        y = min(pred_dat$estimate__), xend = max(pred_dat$lg10.male.weight),
        yend = max(pred_dat$estimate__))) + geom_ribbon(data = pred_dat,
    aes(ymin = lower__, ymax = upper__), fill = "gray", alpha = 0.3) +
    geom_point(color = viridis(10, alpha = 0.6)[7], size = 3) + theme_classic(base_size = 20) +
    labs(x = "log10(male body mass)", y = "log10(female body mass)")

# ggsave(filename =
# './output/log10_male_vs_absolute_SSD_70dpi.tiff', dpi = 70)
# ggsave(filename =
# './output/log10_male_vs_absolute_SSD_300dpi.tiff', dpi = 300)

Male body mass vs absolute SSD

fit <- readRDS("./data/processed/log10_male_vs_abs_SSD.rds")

gg_fit <- conditional_effects(fit)

pred_dat <- gg_fit$lg10.male.weight

fit_summ <- draw_summary(posterior::as_draws_array(fit), variables = c("b_Intercept",
    "b_lg10.male.weight"), robust = TRUE, probs = c(0.025, 0.975))

ggplot(data = dat, mapping = aes(x = lg10.male.weight, y = aboluteSSD)) +
    geom_segment(data = pred_dat, mapping = aes(x = min(pred_dat$lg10.male.weight),
        y = min(pred_dat$estimate__), xend = max(pred_dat$lg10.male.weight),
        yend = max(pred_dat$estimate__))) + geom_ribbon(data = pred_dat,
    aes(ymin = lower__, ymax = upper__), fill = "gray", alpha = 0.3) +
    geom_point(color = viridis(10, alpha = 0.6)[7], size = 3) + theme_classic(base_size = 20) +
    labs(x = "log10(male body mass)", y = "Dimorphism (absolute SSD)")

# ggsave(filename =
# './output/log10_female_vs_absolute_SSD_300dpi.tiff', dpi =
# 300) ggsave(filename =
# './output/log10_female_vs_absolute_SSD_70dpi.tiff', dpi = 70)

Female body mass vs absolute SSD

fit <- readRDS("./data/processed/log10_female_vs_abs_SSD.rds")

gg_fit <- conditional_effects(fit)

pred_dat <- gg_fit$lg10.female.weight

fit_summ <- draw_summary(posterior::as_draws_array(fit), variables = c("b_Intercept",
    "b_lg10.female.weight"), robust = TRUE, probs = c(0.025, 0.975))

ggplot(data = dat, mapping = aes(x = lg10.female.weight, y = aboluteSSD)) +
    # geom_segment(data = pred_dat, mapping = aes(x =
    # min(pred_dat$lg10.female.weight), y =
    # min(pred_dat$estimate__), xend =
    # max(pred_dat$lg10.female.weight), yend =
    # max(pred_dat$estimate__))) + geom_ribbon(data = pred_dat,
    # aes(ymin = lower__, ymax = upper__), fill = 'gray', alpha
    # = 0.3) +
geom_point(color = viridis(10, alpha = 0.6)[7], size = 3) + theme_classic(base_size = 20) +
    labs(x = "log10(female body mass)", y = "Dimorphism (absolute SSD)")

# ggsave(filename =
# './output/male_vs_female_size_10log_300dpi.tiff', dpi = 300)
# ggsave(filename =
# './output/male_vs_female_size_10log_70dpi.tiff', dpi = 70)

Model diagnostics

check_rds_models(path = "./data/processed", html = TRUE)
priors formula iterations chains thinning warmup diverg_transitions rhats > 1.05 min_bulk_ESS min_tail_ESS seed
1 b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) aboluteSSD ~ ln.female.weight + (1 | gr(scientific_name, cov = v.cv.tree)) 10000 4 1 5000 0 0 5290.322 8379.279 65846261
2 b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) ln.male.weight ~ ln.female.weight + (1 | gr(scientific_name, cov = v.cv.tree)) 10000 4 1 5000 0 0 3120.988 4220.375 1212623959
3 b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) aboluteSSD ~ lg10.female.weight + (1 | gr(scientific_name, cov = v.cv.tree)) 10000 4 1 5000 0 0 4821.640 7222.290 1833450209
4 b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) lg10.male.weight ~ lg10.female.weight + (1 | gr(scientific_name, cov = v.cv.tree)) 10000 4 1 5000 0 0 2910.664 4534.518 769877839
5 b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) aboluteSSD ~ lg10.male.weight + (1 | gr(scientific_name, cov = v.cv.tree)) 10000 4 1 5000 0 0 4105.747 7263.945 416614627
6 b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) lg10.female.weight ~ lg10.male.weight + (1 | gr(scientific_name, cov = v.cv.tree)) 10000 4 1 5000 0 0 2882.190 4256.579 408928919
7 b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) aboluteSSD ~ ln.male.weight + (1 | gr(scientific_name, cov = v.cv.tree)) 10000 4 1 5000 0 0 4453.437 8040.974 920571681
8 b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) ln.female.weight ~ ln.male.weight + (1 | gr(scientific_name, cov = v.cv.tree)) 10000 4 1 5000 0 0 2777.937 3908.529 130978144

 

Takeaways

  • Dimorpism increases with body size in males but not in females

 


 

Session information

## R version 4.2.2 Patched (2022-11-10 r83330)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 20.04.5 LTS
## 
## Matrix products: default
## BLAS:   /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.9.0
## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.9.0
## 
## locale:
##  [1] LC_CTYPE=es_ES.UTF-8       LC_NUMERIC=C              
##  [3] LC_TIME=es_CR.UTF-8        LC_COLLATE=es_ES.UTF-8    
##  [5] LC_MONETARY=es_CR.UTF-8    LC_MESSAGES=es_ES.UTF-8   
##  [7] LC_PAPER=es_CR.UTF-8       LC_NAME=C                 
##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
## [11] LC_MEASUREMENT=es_CR.UTF-8 LC_IDENTIFICATION=C       
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
##  [1] ggplot2_3.4.0       viridis_0.6.2       viridisLite_0.4.1  
##  [4] brms_2.18.0         Rcpp_1.0.10         sketchy_1.0.2      
##  [7] brmsish_1.0.0       ggtree_3.6.2        readxl_1.4.1       
## [10] ape_5.6-2           xaringanExtra_0.7.0 rprojroot_2.0.3    
## [13] formatR_1.12        knitr_1.41          kableExtra_1.3.4   
## 
## loaded via a namespace (and not attached):
##   [1] colorspace_2.1-0     ellipsis_0.3.2       ggridges_0.5.4      
##   [4] markdown_1.3         base64enc_0.1-3      aplot_0.1.9         
##   [7] rstudioapi_0.14      farver_2.1.1         rstan_2.21.7        
##  [10] remotes_2.4.2        DT_0.26              fansi_1.0.4         
##  [13] mvtnorm_1.1-3        xml2_1.3.3           codetools_0.2-19    
##  [16] bridgesampling_1.1-2 cachem_1.0.6         shinythemes_1.2.0   
##  [19] bayesplot_1.9.0      jsonlite_1.8.4       packrat_0.8.1       
##  [22] ggdist_3.2.1         shiny_1.7.3          compiler_4.2.2      
##  [25] httr_1.4.4           backports_1.4.1      Matrix_1.5-1        
##  [28] fastmap_1.1.0        lazyeval_0.2.2       cli_3.6.0           
##  [31] later_1.3.0          prettyunits_1.1.1    htmltools_0.5.4     
##  [34] tools_4.2.2          igraph_1.3.5         coda_0.19-4         
##  [37] gtable_0.3.1         glue_1.6.2           reshape2_1.4.4      
##  [40] dplyr_1.0.10         posterior_1.3.1      cellranger_1.1.0    
##  [43] jquerylib_0.1.4      vctrs_0.5.2          svglite_2.1.0       
##  [46] nlme_3.1-162         crosstalk_1.2.0      tensorA_0.36.2      
##  [49] xfun_0.35            stringr_1.5.0        ps_1.7.2            
##  [52] rvest_1.0.3          mime_0.12            miniUI_0.1.1.1      
##  [55] lifecycle_1.0.3      gtools_3.9.3         zoo_1.8-11          
##  [58] scales_1.2.1         colourpicker_1.2.0   promises_1.2.0.1    
##  [61] Brobdingnag_1.2-9    parallel_4.2.2       inline_0.3.19       
##  [64] shinystan_2.6.0      yaml_2.3.6           pbapply_1.6-0       
##  [67] gridExtra_2.3        ggfun_0.0.9          StanHeaders_2.21.0-7
##  [70] loo_2.5.1            yulab.utils_0.0.6    sass_0.4.4          
##  [73] stringi_1.7.12       highr_0.9            dygraphs_1.1.1.6    
##  [76] tidytree_0.4.2       checkmate_2.1.0      pkgbuild_1.3.1      
##  [79] rlang_1.0.6          pkgconfig_2.0.3      systemfonts_1.0.4   
##  [82] matrixStats_0.62.0   distributional_0.3.1 evaluate_0.19       
##  [85] lattice_0.20-45      purrr_1.0.1          labeling_0.4.2      
##  [88] treeio_1.23.0        rstantools_2.2.0     patchwork_1.1.2     
##  [91] htmlwidgets_1.5.4    cowplot_1.1.1        processx_3.8.0      
##  [94] tidyselect_1.2.0     plyr_1.8.7           magrittr_2.0.3      
##  [97] R6_2.5.1             generics_0.1.3       withr_2.5.0         
## [100] pillar_1.8.1         xts_0.12.2           abind_1.4-5         
## [103] tibble_3.1.8         crayon_1.5.2         uuid_1.1-0          
## [106] utf8_1.2.2           rmarkdown_2.19       grid_4.2.2          
## [109] callr_3.7.3          threejs_0.3.3        digest_0.6.31       
## [112] webshot_0.5.4        xtable_1.8-4         tidyr_1.3.0         
## [115] httpuv_1.6.6         gridGraphics_0.5-1   RcppParallel_5.1.5  
## [118] stats4_4.2.2         munsell_0.5.0        ggplotify_0.1.0     
## [121] bslib_0.4.2          shinyjs_2.1.0